=begin pod

=TITLE class Int

=SUBTITLE Integer (arbitrary-precision)

=for code :skip-test
class Int is Cool does Real { }

C<Int> objects store integral numbers of arbitrary size. C<Int>s are immutable.

There are two main syntax forms for C<Int> literals

    123;         # Int in decimal notation
    :16<BEEF>;   # Int in radix notations

For your convenience common radix forms come with a prefix shortcut.

    say so :2<11111111> == 0b11111111 == :8<377> == 0o377 == 255 == 0d255 == :16<ff> == 0xff;
    # OUTPUT: «True␤»

All forms allow underscores between any two digits which can serve as visual
separators, but don't carry any meaning:

    5_00000;       # five Lakhs
    500_000;       # five hundred thousand
    0xBEEF_CAFE;   # a strange place
    :2<1010_1010>; # 0d170

Radix notation also supports round and angle brackets which allow you to parse
a string for a given base, and putting together digits into a whole number
respectively:

    :16("9F");         # 159
    :100[99, 2, 3];    # 990203

These notations allow you to use variables, too:

    my $two = "2";
    my $ninety-nine = "99";
    :16($ninety-nine); # 153
    :100[99, $two, 3]; # 990203

=head1 Methods

=head2 method Capture

Defined as:

    method Capture()

Throws C<X::Cannot::Capture>.

=head2 routine chr

Defined as:

    multi sub    chr(Int:D  --> Str:D)
    multi method chr(Int:D: --> Str:D)

Returns a one-character string, by interpreting the integer as a Unicode
codepoint number and converting it to the corresponding character.

Example:

    65.chr;  # returns "A"
    196.chr; # returns "Ä"

=head2 routine expmod

Defined as:

    multi sub    expmod(      $x,     $y,     $mod --> Int:D)
    multi sub    expmod(Int:D $x, Int $y, Int $mod --> Int:D)
    multi method expmod(Int:D:    Int $y, Int $mod --> Int:D)

Returns the given C<Int> raised to the C<$y> power within modulus C<$mod>,
that is gives the result of C<($x ** $y) mod $mod>. The subroutine form
can accept non-C<Int> arguments, which will be coerced to C<Int>.

    say expmod(4, 2, 5);    # OUTPUT: «1␤»
    say 7.expmod(2, 5);     # OUTPUT: «4␤»

=head2 method polymod

Defined as:

    method polymod(Int:D: +@mods)

Returns a sequence of mod results corresponding to the divisors in C<@mods>.
The divisors are given from smallest "unit" to the largest
(e.g. 60 seconds per minute, 60 minutes per hour) and the results
are returned in the same way: from smallest to the largest
(5 seconds, 4 minutes).

Returns one more item in the result than the number of given divisors.
If the divisors are given as a lazy list, runs until the remainder is 0 or
the list of divisors is exhausted. All divisors must be C<Int>s, unless
the method is called on a non-C<Int> number.

    my $seconds = 1 * 60*60*24 # days
                + 3 * 60*60    # hours
                + 4 * 60       # minutes
                + 5;           # seconds

    say $seconds.polymod(60, 60);                # OUTPUT: «(5 4 27)␤»
    say $seconds.polymod(60, 60, 24);            # OUTPUT: «(5 4 3 1)␤»

    say 120.polymod:      1, 10, 10², 10³, 10⁴;  # OUTPUT: «(0 0 12 0 0 0)␤»
    say 120.polymod: lazy 1, 10, 10², 10³, 10⁴;  # OUTPUT: «(0 0 12)␤»
    say 120.polymod:      1, 10, 10² … ∞;        # OUTPUT: «(0 0 12)␤»

    say ⅔.polymod(⅓);                            # OUTPUT: «(0 2)␤»
    say 5.Rat.polymod(.3, .2);                   # OUTPUT: «(0.2 0 80)␤»

    my @digits-in-base37 = 9123607.polymod(37 xx *); # Base conversion
    say @digits-in-base37.reverse                    # OUTPUT: «[4 32 4 15 36]␤»


To illustrate how the C<Int>, non-lazy version of polymod works, consider
this code that implements it:

    my $seconds = 2 * 60*60*24 # days
                + 3 * 60*60    # hours
                + 4 * 60       # minutes
                + 5;           # seconds

    my @pieces;
    for 60, 60, 24 -> $divisor {
        @pieces.push: $seconds mod $divisor;
        $seconds div= $divisor
    }
    @pieces.push: $seconds;

    say @pieces; # OUTPUT: «[5 4 3 2]␤»

For a more detailed discussion, see
L<this blog post|http://perl6.party/post/Perl6-.polymod-break-up-a-number-into-denominations>

=head2 routine is-prime

Defined as:

    multi sub    is-prime (Int:D $number --> Bool:D)
    multi method is-prime (Int:D: --> Bool:D)

Returns C<True> if this C<Int> is known to be a prime, or is likely to be a
prime based on a probabilistic Miller-Rabin test.

Returns C<False> if this C<Int> is known not to be a prime.

    say 2.is-prime;         # OUTPUT: «True␤»
    say is-prime(9);        # OUTPUT: «False␤»

=head2 routine lsb

Defined as:

    multi method lsb(Int:D:)
    multi sub    lsb(Int:D)

Returns L<Nil|/type/Nil> if the number is 0. Otherwise returns the zero-based
index from the right of the least significant (rightmost) 1 in the binary
representation of the number.

    say 0b01011.lsb;        # OUTPUT: «0␤»
    say 0b01010.lsb;        # OUTPUT: «1␤»
    say 0b10100.lsb;        # OUTPUT: «2␤»
    say 0b01000.lsb;        # OUTPUT: «3␤»
    say 0b10000.lsb;        # OUTPUT: «4␤»

=head2 routine msb

Defined as:

    multi method msb(Int:D:)
    multi sub    msb(Int:D)

Returns L<Nil|/type/Nil> if the number is 0. Otherwise returns the zero-based
index from the right of the most significant (leftmost) 1 in the binary
representation of the number.

    say 0b00001.msb;        # OUTPUT: «0␤»
    say 0b00011.msb;        # OUTPUT: «1␤»
    say 0b00101.msb;        # OUTPUT: «2␤»
    say 0b01010.msb;        # OUTPUT: «3␤»
    say 0b10011.msb;        # OUTPUT: «4␤»

=head2 routine unival

Defined as:

    multi sub    unival(Int:D  --> Numeric)
    multi method unival(Int:D: --> Numeric)

Returns the number represented by the Unicode codepoint with the given integer
number, or L<NaN|/type/Num#NaN> if it does not represent a number.

    say ord("¾").unival;    # OUTPUT: «0.75␤»
    say 190.unival;         # OUTPUT: «0.75␤»
    say unival(65);         # OUTPUT: «NaN␤»

=head1 Operators

=head2 infix div

    multi sub infix:<div>(Int:D, Int:D --> Int:D)

Does an integer division, rounded down.

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
